今天終於久違的真正完成了一個項目,一起來看看效果跟 code 吧!
我就直接在 code 裡註記 操作囉~
import { useEffect, useRef } from "react";
import "./styles.css";
let player = 1;
const lineColor = "#ddd";
const canvasSize = 500;
const sectionSize = canvasSize / 3;
export default function App() {
const canvasRef = useRef(null);
useEffect(() => {
// 首次載入時,畫上井字線
if (canvasRef.current) drawLines(10, lineColor);
}, [canvasRef]);
/**
* 每次滑鼠點擊時,替換選手
* @param {*} event
*/
const handleMouseDown = (event) => {
if (canvasRef.current) {
if (player === 1) {
player = 2;
} else {
player = 1;
}
const canvasMousePosition = getCanvasMousePosition(event);
addPlayingPiece(canvasMousePosition);
drawLines(10, lineColor);
}
};
/** 依點擊位置決定繪製範圍 */
const addPlayingPiece = (mouse) => {
let xCordinate;
let yCordinate;
for (let x = 0; x < 3; x++) {
for (let y = 0; y < 3; y++) {
xCordinate = x * sectionSize;
yCordinate = y * sectionSize;
if (
mouse.x >= xCordinate &&
mouse.x <= xCordinate + sectionSize &&
mouse.y >= yCordinate &&
mouse.y <= yCordinate + sectionSize
) {
/** */
clearPlayingArea(xCordinate, yCordinate);
if (player === 1) {
drawX(xCordinate, yCordinate);
} else {
drawO(xCordinate, yCordinate);
}
}
}
}
};
/** 畫圈圈 */
const drawO = (xCordinate, yCordinate) => {
const context = canvasRef.current.getContext("2d");
const halfSectionSize = 0.5 * sectionSize;
const centerX = xCordinate + halfSectionSize;
const centerY = yCordinate + halfSectionSize;
const radius = (sectionSize - 100) / 2;
const startAngle = 0 * Math.PI;
const endAngle = 2 * Math.PI;
context.lineWidth = 10;
context.strokeStyle = "#01bBC2";
context.beginPath();
context.arc(centerX, centerY, radius, startAngle, endAngle);
context.stroke();
};
/** 畫叉叉 */
const drawX = (xCordinate, yCordinate) => {
const context = canvasRef.current.getContext("2d");
context.strokeStyle = "#f1be32";
context.beginPath();
const offset = 50;
context.moveTo(xCordinate + offset, yCordinate + offset);
context.lineTo(
xCordinate + sectionSize - offset,
yCordinate + sectionSize - offset
);
context.moveTo(xCordinate + offset, yCordinate + sectionSize - offset);
context.lineTo(xCordinate + sectionSize - offset, yCordinate + offset);
context.stroke();
};
const drawLines = (lineWidth, strokeStyle) => {
const context = canvasRef.current.getContext("2d");
const lineStart = 4;
const lineLenght = canvasSize - 5;
context.lineWidth = lineWidth;
context.lineCap = "round";
context.strokeStyle = strokeStyle;
context.beginPath();
/*
* Horizontal lines
*/
for (let y = 1; y <= 2; y++) {
context.moveTo(lineStart, y * sectionSize);
context.lineTo(lineLenght, y * sectionSize);
}
/*
* Vertical lines
*/
for (let x = 1; x <= 2; x++) {
context.moveTo(x * sectionSize, lineStart);
context.lineTo(x * sectionSize, lineLenght);
}
context.stroke();
};
/** 清空畫布 */
const clearPlayingArea = (xCordinate, yCordinate) => {
if (canvasRef.current) {
const context = canvasRef.current.getContext("2d");
context.fillStyle = "#fff";
context.fillRect(xCordinate, yCordinate, sectionSize, sectionSize);
}
};
const getCanvasMousePosition = (event) => {
const rect = canvasRef.current.getBoundingClientRect();
return {
x: event.clientX - rect.left,
y: event.clientY - rect.top
};
};
return (
<div className="App">
<div className="center-wrapper-parent">
<div className="canvas-wrapper">
<canvas
width={canvasSize}
height={canvasSize}
ref={canvasRef}
className="center-v"
onMouseDown={handleMouseDown}
></canvas>
</div>
</div>
</div>
);
}